﻿//Created: 03/29/2013 @ 11:30pm by Azriel Del Monté
//Last change date: 03/29/2013 @ 11:40pm by Azriel Del Monté

using Action = Styx.TreeSharp.Action;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Template
{
    public class Main : CombatRoutine
    {
        public override string Name { get { return "Death Knight(Frost) 1H"; } }
        public override WoWClass Class { get { return WoWClass.DeathKnight; } }
        LocalPlayer Me { get { return StyxWoW.Me; } }

        private Composite _preCombatBuffs, _combatBuffs, _Heal, _Combat;
        public override Composite PreCombatBuffBehavior { get { return _preCombatBuffs; } }
        public override Composite CombatBuffBehavior { get { return _combatBuffs; } }
        public override Composite HealBehavior { get { return _Heal; } }
        public override Composite CombatBehavior { get { return _Combat; } }

        #region Initialize
        public override void Initialize()
        {
            _preCombatBuffs = createPreCombatBuffs();
            _combatBuffs = createCombatBuffs();
            _Heal = createHeal();
            _Combat = createCombat();
            DpsInfos.Clear();
        }
        #endregion

        #region Pre-Combat Buffs
        Composite createPreCombatBuffs()
        {
            return
                new Decorator(ret => Manual,
                    new PrioritySelector(
                        //0 	0.00 	flask,type=winters_bite
                        //1 	0.00 	food,type=black_pepper_ribs_and_shrimp
                        //2 	0.00 	frost_presence
                        //3 	0.00 	horn_of_winter
                        //5 	0.00 	army_of_the_dead
                        //6 	0.00 	mogu_power_potion
                        //7 	0.00 	blood_fury
                        //8 	0.00 	pillar_of_frost
                        //9 	0.00 	raise_dead
                        ));
        }
        #endregion

        #region Combat Buffs
        Composite createCombatBuffs()
        {
            return
                new Decorator(ret => Manual,
                    new PrioritySelector(
                        //A 	1.00 	auto_attack
                        //B 	6.90 	pillar_of_frost
                        //C 	1.00 	mogu_power_potion,if=target.time_to_die<=30|(target.time_to_die<=60&buff.pillar_of_frost.up)
                        //D 	0.17 	empower_rune_weapon,if=target.time_to_die<=60&(buff.mogu_power_potion.up|buff.golemblood_potion.up)
                        //E 	7.90 	use_item,name=gauntlets_of_the_allconsuming_maw,if=buff.pillar_of_frost.up
                        //F 	3.33 	blood_fury
                        //G 	3.33 	raise_dead
                        ));
        }
        #endregion

        #region Heal
        Composite createHeal()
        {
            return
                new Decorator(ret => Manual,
                    new PrioritySelector(
                        ));
        }
        #endregion

        #region Combat
        Composite createCombat()
        {
            return
                new Decorator(ret => Manual,
                    new PrioritySelector(
                        //H 	0.00 	run_action_list,name=aoe,if=active_enemies>=5
                        //I 	0.00 	run_action_list,name=single_target,if=active_enemies<5

                        //X 	6.95 	blood_tap,if=talent.blood_tap.enabled&buff.blood_charge.stack>10&(runic_power>76|(runic_power>=20&buff.killing_machine.react))
                        //Y 	83.57 	frost_strike,if=buff.killing_machine.react|runic_power>88
                        //Z 	14.16 	plague_leech,if=talent.plague_leech.enabled&(dot.blood_plague.remains<3|dot.frost_fever.remains<3|cooldown.outbreak.remains<1)
                        //a 	7.88 	outbreak,if=dot.frost_fever.remains<3|dot.blood_plague.remains<3
                        //b 	0.00 	unholy_blight,if=talent.unholy_blight.enabled&(dot.frost_fever.remains<3|dot.blood_plague.remains<3)
                        //c 	32.22 	soul_reaper,if=target.health.pct-3*(target.health.pct%target.time_to_die)<=45
                        //d 	15.50 	blood_tap,if=talent.blood_tap.enabled&(target.health.pct-3*(target.health.pct%target.time_to_die)<=45&cooldown.soul_reaper.remains=0)
                        //e 	7.26 	howling_blast,if=!dot.frost_fever.ticking
                        //f 	7.35 	plague_strike,if=!dot.blood_plague.ticking
                        //g 	18.82 	howling_blast,if=buff.rime.react
                        //h 	29.78 	frost_strike,if=runic_power>76
                        //i 	5.79 	obliterate,if=unholy>1
                        //j 	10.24 	howling_blast,if=death>1|frost>1
                        //k 	20.32 	horn_of_winter
                        //l 	38.84 	obliterate,if=unholy>0
                        //m 	89.11 	howling_blast
                        //n 	0.00 	frost_strike,if=talent.runic_empowerment.enabled&(frost=0|blood=0)
                        //o 	41.62 	blood_tap,if=talent.blood_tap.enabled&(target.health.pct-3*(target.health.pct%target.time_to_die)>45|buff.blood_charge.stack>=8)
                        //p 	0.00 	frost_strike,if=talent.runic_corruption.enabled&buff.runic_corruption.down
                        //q 	6.56 	death_and_decay
                        //r 	50.35 	frost_strike,if=runic_power>=40
                        //s 	1.40 	empower_rune_weapon
                        ));
        }
        #endregion

        #region Methods

        #region Buff Checks
        public bool buffExists(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                    return true;
            }
            return false;
        }
        public double buffTimeLeft(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                {
                    if (Results.TimeLeft.TotalMilliseconds > 0)
                        return Results.TimeLeft.TotalMilliseconds;
                }
            }
            return 0;
        }
        public uint buffStackCount(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                    return Results.StackCount;
            }
            return 0;
        }
        #endregion

        #region Cooldown Checks
        public TimeSpan spellCooldownLeft(int Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                if (Results.Override != null)
                    return Results.Override.CooldownTimeLeft;
                return Results.Override.CooldownTimeLeft;
            }
            return TimeSpan.MaxValue;
        }
        public bool spellOnCooldown(int Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
                return Results.Override != null ? Results.Override.Cooldown : Results.Original.Cooldown;
            return false;
        }
        #endregion

        #region Debuff Checks
        public bool debuffExists(int debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(debuff);
                if (Results != null)
                    return true;
            }
            return false;
        }
        public double debuffTimeLeft(int debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(debuff);
                if (Results != null)
                {
                    if (Results.TimeLeft.TotalMilliseconds > 0)
                        return Results.TimeLeft.TotalMilliseconds;
                }
            }
            return 0;
        }
        public uint debuffStackCount(int debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(debuff);
                if (Results != null)
                    return Results.StackCount;
            }
            return 0;
        }
        #endregion

        #region Macro Checks
        public bool AoE { get { return Convert.ToBoolean(Lua.GetReturnVal<int>("return AoE and 0 or 1", 0)); } }
        public bool Manual { get { return Convert.ToBoolean(Lua.GetReturnVal<int>("return Manual and 0 or 1", 0)); } }
        public bool useCDs { get { return Convert.ToBoolean(Lua.GetReturnVal<int>("return UseCDs and 0 or 1", 0)); } }
        #endregion

        #region Target Checks
        public bool gotTarget { get { return Me.GotTarget && Me.CurrentTarget != null && (Me.CurrentTarget.IsAlive && !Me.CurrentTarget.IsFriendly || isTargetDummy); } }
        public bool isTargetDummy { get { return Me.CurrentTarget.Name == "Training Dummy" || Me.CurrentTarget.Name == "Raider's Training Dummy"; } }
        public double targetDistance(WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.DistanceSqr;
                if (Results != null)
                    return onTarget.DistanceSqr;
            }
            return 0;
        }
        public double targetHP(WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.HealthPercent;
                if (Results != null)
                    return onTarget.HealthPercent;
            }
            return 0;
        }
        #endregion

        #region Spell Casting
        private Composite autoAttack()
        {
            return
                new PrioritySelector(
                    new Decorator(ret => !StyxWoW.Me.IsAutoAttacking,
                        new Action(ret =>
                        {
                            Lua.DoString("StartAttack()");
                            return RunStatus.Failure;
                        }))
                    );
        }
        private delegate T Selection<out T>(object Context);
        public Composite Cast(int Spell, Selection<bool> reqs = null, Selection<WoWUnit> onTarget = null, bool ignoreCanCast = false)
        {
            return
                new Decorator(ret =>
                {
                    if (reqs != null && !reqs(ret))
                        return false;
                    if (!ignoreCanCast && !SpellManager.CanCast(Spell, onTarget != null ? onTarget(ret) : Me.CurrentTarget))
                        return false;
                    return true;
                },
                    new Action(ret =>
                    {
                        WoWSpell castingSpell = Me.CastingSpell;
                        if (castingSpell != null && castingSpell.Id != Spell)
                            Lua.DoString("SpellStopCasting()");
                        Logging.Write("Casting: " + Spell + " on " + Me.CurrentTarget.Name);
                        SpellManager.Cast(Spell, (onTarget != null ? onTarget(ret) : null));
                    })
                    );
        }
        public Composite dropCast(int Spell, Selection<bool> reqs = null, Selection<WoWUnit> onTarget = null, bool ignoreCanCast = false)
        {
            return
                new Decorator(ret =>
                {
                    if (reqs != null && !reqs(ret))
                        return false;
                    if (!ignoreCanCast && !SpellManager.CanCast(Spell, onTarget != null ? onTarget(ret) : Me.CurrentTarget))
                        return false;
                    return true;
                },
                    new Action(ret =>
                    {
                        WoWSpell castingSpell = Me.CastingSpell;
                        if (castingSpell != null && castingSpell.Id != Spell)
                            Lua.DoString("SpellStopCasting()");
                        Logging.Write("Casting: " + Spell + " on " + Me.CurrentTarget.Name);
                        SpellManager.Cast(Spell, (onTarget != null ? onTarget(ret) : null));
                        SpellManager.ClickRemoteLocation(Me.CurrentTarget.Location);
                    })
                    );
        }
        #endregion

        #endregion
    }
}

